package cn.e4j.modular.api.util;

import cn.e4j.config.properties.E4jProperties;
import cn.e4j.core.dto.impl.Dto;
import cn.e4j.core.log.factory.LogFactory;
import cn.e4j.core.util.SpringContextHolder;
import cn.e4j.core.util.ToolUtil;
import com.alibaba.fastjson.*;
import org.apache.poi.ss.formula.functions.T;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @ClassName: CommonUtils
 * @Author: caijy
 * @Date: 2019-6-26 0026 13:24
 * @Description:TODO
 */
public class CommonUtils extends ToolUtil{
    public static final Logger logger = LoggerFactory.getLogger(CommonUtils.class);

    public static final int calendarField=5;

    public static final int returnHour=1;

    public static final int returnMinute=2;

    public static final int returnSeconds=3;


    public static String getLang(String lang_){
        String lang="2";
        if ("zh_CN".equals(lang_)){
            lang="2";
        }else if ("zh_TW".equals(lang_)){
            lang="0";
        }else if ("en".equals(lang_)){
            lang="1";
        }
        return lang;
    }

    public static <T> T toJavaClass(Object target,Class<T> clazz){
        String jsonString = JSON.toJSONString(target);
        JSONObject jsonObject = JSON.parseObject(jsonString);
        //防止转成实体的localdate出现的异常
        for (String key:jsonObject.keySet()){
            String value = jsonObject.getString(key);
            if (value.contains(" 00:00:00")){
                jsonObject.put(key,value.replace(" 00:00:00",""));
            }
        }
        return JSON.parseObject(JSON.toJSONString(jsonObject),clazz);
    }

    public static JSONArray toJSONArray(String listJsonString){
        return JSONArray.parseArray(listJsonString);
    }

    public static <T> List<T> toJavaList(String listJsonString, Class<T> clazz){
        if (clazz.getSimpleName().equalsIgnoreCase("Dto")){

            return (List<T>)JSONObject.parseArray(listJsonString, Dto.class);
        }
        return toJSONArray(listJsonString).toJavaList(clazz);
    }

    /**
     *功能描述
     * @author caijy
     * @description  java8 localdate与date转换
     * @datetime 2019-11-11 0011 10:16
     * @param date
     * @return java.time.LocalDate
     */
    public static LocalDate dateToLocalDate(Date date){

        if (date==null)
            return null;

        Instant instant = null;
        try {
            //执行这步可能会抛出异常 数据库获取到的date会执行java.sql.Date.toInstant
            instant = date.toInstant();
        }catch (UnsupportedOperationException e){
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            instant = calendar.toInstant();
        }
        return isEmpty(date)?null:instant.atZone(ZoneId.systemDefault()).toLocalDate();
    }

    /**
     *功能描述
     * @author caijy
     * @description  java8 localdate与date转换
     * @datetime 2019-11-11 0011 10:16
     * @param date
     * @return java.util.Date
     */
    public static Date localDateToDate(LocalDate date){

        if (date==null)
            return null;

        return isEmpty(date)?null:Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant());
    }

    /**
     *功能描述
     * @author caijy
     * @description java8 计算增加天数
     * @datetime 2019-11-11 0011 10:28
     * @param date
     * @param amount
     * @return java.time.LocalDate
     */
    public static LocalDate addDays(LocalDate date,int amount){
        Calendar c = Calendar.getInstance();
        c.setTime(localDateToDate(date));
        c.add(calendarField, amount);

        return c.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
    }

    public static LocalDateTime StringToLocalDateTime(String str){
        LocalDateTime time = null;
        try {
            if(isNotEmpty(str)){
                if (str.length() == 16) {
                    str += ":00";
                }
                time = LocalDateTime.parse(str, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            }
        }catch (DateTimeParseException e){
            //将ISO 8601字符串转换回LocalDateTime 类似2016-02-14T18:32:04.150Z
            time =LocalDateTime.parse(str);

        }catch (Exception e){
            e.printStackTrace();
        }
        return time;
    }

    public static LocalDateTime addMinutes(Object timeObj,long amount){

        if (isEmpty(timeObj))
            return null;

        LocalDateTime time = null;
        if (timeObj instanceof String)
            time = StringToLocalDateTime(timeObj+"");

        return time.plusMinutes(amount);
    }

    /**
     *功能描述
     * @author caijy
     * @description timeObjA 早于 timeObjB
     * @datetime 2019-11-30 0030 11:57
     * @param timeObjA
     * @param timeObjB
     * @return java.lang.Boolean
     */
    public static Boolean isBefore(Object timeObjA,Object timeObjB){

        if (isEmpty(timeObjA) || isEmpty(timeObjB))
            return null;


        LocalDateTime time1 = null;
        LocalDateTime time2 = null;
        if (timeObjA instanceof String)
            time1 = StringToLocalDateTime(timeObjA+"");
        if (timeObjA instanceof LocalDateTime)
            time1 = (LocalDateTime)timeObjA;

        if (timeObjB instanceof String)
            time2 = StringToLocalDateTime(timeObjB+"");
        if (timeObjB instanceof LocalDateTime)
            time2 = (LocalDateTime)timeObjB;

        return time1.isBefore(time2);
    }

    /**
     *功能描述
     * @author caijy
     * @description timeObjA 晚于 timeObjB
     * @datetime 2019-11-30 0030 11:57
     * @param timeObjA
     * @param timeObjB
     * @return java.lang.Boolean
     */
    public static Boolean isAfter(Object timeObjA,Object timeObjB){

        if (isEmpty(timeObjA) || isEmpty(timeObjB))
            return null;

        LocalDateTime time1 = null;
        LocalDateTime time2 = null;
        if (timeObjA instanceof String)
            time1 = StringToLocalDateTime(timeObjA+"");
        if (timeObjA instanceof LocalDateTime)
            time1 = (LocalDateTime)timeObjA;

        if (timeObjB instanceof String)
            time2 = StringToLocalDateTime(timeObjB+"");
        if (timeObjB instanceof LocalDateTime)
            time2 = (LocalDateTime)timeObjB;

        return time1.isAfter(time2);
    }

    /**
     * 计算时间差
     * @author caijy
     * @description
     * @datetime 2019-12-6 0006 16:07
     * @param start
     * @param end
     * @param returnType 返回的类型 1.时 2.分 3.秒
     * @return java.lang.Long
     */
    public static Long diffTime(LocalDateTime start,LocalDateTime end,int returnType){

        if (isEmpty(start) || isEmpty(end))
            return null;

//        logger.info("*****************Duration******************");
        Duration duration = Duration.between(start, end);

        switch (returnType){
            case returnHour:
//                logger.info("时间差："+duration.toHours()+"小时");
                return duration.toHours();
            case returnMinute:
//                logger.info("时间差："+duration.toMinutes()+"分钟");
                return duration.toMinutes();
            case returnSeconds:
//                logger.info("时间差："+duration.getSeconds()+"秒");
                return duration.getSeconds();
        }
//        logger.info("*****************Duration******************");
//
//        logger.info("*****************Period 计算年月日 适用于日以上的计算 ******************");
//        //2019-12-05 17:00:00 2019-12-06 17:30:15
//        Period period = Period.between(start.toLocalDate(), end.toLocalDate());
//        logger.info("时间差："+period.getYears()+"年");//2019-2019
//        logger.info("时间差："+period.getMonths()+"月");//12-12
//        logger.info("时间差："+period.getDays()+"日");//6-5
//
//        logger.info("*****************Period 计算年月日******************");
//
//        logger.info("*****************ChronoUnit 计算单个时间******************");
//        logger.info("时间差："+ChronoUnit.DAYS.between(start.toLocalDate(),end.toLocalDate())+"日");
//        logger.info("时间差："+ChronoUnit.MINUTES.between(start,end)+"分钟");
//        logger.info("时间差："+ChronoUnit.DAYS.between(start,end)+"日");
//        logger.info("*****************ChronoUnit******************");

        return null;
    }

    @Autowired
    E4jProperties e4jProperties;

    public <T> T exe(Class clazz, String methodName, Object... params){
        Method method = null;
        T result = null;
        try {
            Class<Object>[] parameterType = new Class[params.length];
            for (int i = 0; i < params.length; i++) {
                parameterType[i] = (Class<Object>) (params[i]).getClass();
            }
            String simpleName = clazz.getSimpleName();
            Object tClass = SpringContextHolder.getBean(simpleName.substring(0,1).toLowerCase()+simpleName.substring(1,simpleName.length()));
            switch (e4jProperties.getDbType()){
                case "oracle":
                    method = tClass.getClass().getMethod(methodName+"Ora", parameterType);
                    break;
                case "sqlserver":
                    method = tClass.getClass().getMethod(methodName, parameterType);
            }
            result = (T)method.invoke(tClass,params);
        }catch (IllegalAccessException e){
            e.printStackTrace();
        }catch (NoSuchMethodException e){
            e.printStackTrace();
        }catch (Exception e){
            e.printStackTrace();
        }

        return result;
    }


    public static void main(String[] args) {
        diffTime(LocalDateTime.of(2018,11,5,17,00,00),
                LocalDateTime.of(2019,12,6,17,30,15),1);
    }
}
